package cn.djx.springsecurity.service.impl;

import cn.djx.springsecurity.constants.Constants;
import cn.djx.springsecurity.entity.LoginUsers;
import cn.djx.springsecurity.entity.Users;
import cn.djx.springsecurity.mapper.UsersMapper;
import cn.djx.springsecurity.service.LoginService;
import cn.djx.springsecurity.utils.RedisUtil;
import cn.djx.springsecurity.utils.ResponseResult;
import cn.hutool.jwt.JWTUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class LoginServiceImpl implements LoginService {
    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private UsersMapper usersMapper;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private ObjectMapper objectMapper;
    /**
     * 用户登录方法
     * @param users 包含用户名和密码的用户对象
     * @return ResponseResult 登录结果，包含状态码、消息和token数据
     * @throws JsonProcessingException JSON处理异常
     */
    @Override
    public ResponseResult login(Users users) throws JsonProcessingException {
        // 进行登录验证
        // 创建包含用户名和密码的身份验证令牌
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(users.getUserName(), users.getPassword());
        // 进行身份验证
        Authentication auth = authenticationManager.authenticate(authenticationToken);
        if (Objects.isNull(auth)){
            throw new RuntimeException("登录失败");
        }
        // 验证通过
        // 将身份验证后的用户信息转换为LoginUsers对象
        LoginUsers loginUsers = (LoginUsers) auth.getPrincipal();

        // 生成token并将登录用户信息存储到redis中
        // 设置JWT token的参数
        Map<String, Object> jwtMap = new HashMap<String, Object>() {
            {
                // 设置token的用户id
                put("uid", loginUsers.getUsers().getId());
                // 设置token的过期时间为15天
                put("expire_time", System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 15);
            }
        };
        // 使用JWT工具类生成token
        String token = JWTUtil.createToken(jwtMap, "1234".getBytes());
        // 将登录用户信息存储到redis中
        redisUtil.set(Constants.redis_token+loginUsers.getUsers().getId(), objectMapper.writeValueAsString(loginUsers));
        // 构建包含token的map作为登录成功的返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        return new ResponseResult(200,"登录成功",result);
    }


    @Override
    public ResponseResult register(Users users) {
        // 密码加密
        users.setPassword(passwordEncoder.encode(users.getPassword()));
        // 保存用户信息到数据库
        int row = usersMapper.insert(users);
        if (row > 0){
            return new ResponseResult(200,"注册成功",null);
        }
        return new ResponseResult(500,"注册失败",null);
    }

    @Override
    public ResponseResult logout() {
        // 获取当前认证信息
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        // 获取登录用户信息
        LoginUsers loginUsers = (LoginUsers) auth.getPrincipal();
        // 从redis中移除用户的token
        redisUtil.remove(Constants.redis_token+loginUsers.getToken());
        // 清空当前认证信息
        SecurityContextHolder.getContext().setAuthentication(null);
        // 返回注销成功的响应结果
        return new ResponseResult(200,"注销成功",null);
    }

}
